package com.fs.sys.service;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.fs.sys.bean.dto.DeptDTO;
import com.fs.sys.bean.dto.TenantDTO;
import com.fs.sys.bean.dto.UserDTO;
import com.fs.sys.entityservice.AppEntityService;
import com.fs.sys.entityservice.DataSubEntityService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Map;

/**
 * 基础数据推送
 *
 * @author LiuQi 2025/6/11-13:17
 * @version V1.0
 **/
@Service
@Slf4j
public class SysDataSyncService {
    @Autowired(required = false)
    private RabbitTemplate rabbitTemplate;

    @Value("${spring.rabbitmq.queues.dept}")
    private String deptQueue;

    @Value("${spring.rabbitmq.queues.user}")
    private String userQueue;

    @Value("${spring.rabbitmq.queues.tenant}")
    private String tenantQueue;

    @Value("${spring.rabbitmq.enabled}")
    private Boolean enabled;

    @Autowired
    private DataSubEntityService dataSubEntityService;

    @Autowired
    private AppEntityService appEntityService;

    /**
     * 租户更新或新增时推送
     * @param tenant 机构信息
     */
    @Async
    public void sendTenant(TenantDTO tenant) {
        if (!enabled) {
            log.warn("未启用RabbitMQ");
            return;
        }

        Msg<TenantDTO> msg = new Msg<>();
        msg.setData(tenant);
        msg.setType("save");
        Message message = new Message(JSON.toJSONString(msg).getBytes());
        rabbitTemplate.convertAndSend(tenantQueue + ".topic", "tenant", message);
    }

    /**
     * 机构更新或新增时推送
     * @param dept 机构信息
     */
    @Async
    public void sendDeptData(DeptDTO dept) {
        processDataSub("dept", "save", dept);

        if (!enabled) {
            log.warn("未启用RabbitMQ");
            return;
        }

        Msg<DeptDTO> msg = new Msg<>();
        msg.setData(dept);
        msg.setType("save");
        Message message = new Message(JSON.toJSONString(msg).getBytes());
        String tenantId = dept.getTenantId();
        rabbitTemplate.convertAndSend(deptQueue + ".topic", tenantId, message);
    }

    /**
     * 处理数据订阅
     * @param data 推送数据
     */
    private void processDataSub(String dataType, String operationType, Object data) {
        // 应用配置订阅数据处理
        appEntityService.findAll()
                        .forEach(app -> {
                            Map<String, Object> metadata = app.getMetadata();
                            if (null == metadata) {
                                return;
                            }
                            Map<String, String> webhooks = (Map<String, String>) metadata.get("webhooks");
                            if (null == webhooks) {
                                return;
                            }

                            webhooks.forEach((k, v) -> {
                                if (k.startsWith(dataType) && k.toLowerCase().endsWith(operationType)) {
                                    sendByWebhook(data, v);
                                }
                            });
                        });

        dataSubEntityService.findByDataType(dataType, operationType).forEach(dataSub -> {
            String url = dataSub.getUrl();
            sendByWebhook(data, url);
        });
    }

    /**
     * 通过webhook推送数据
     * @param data 待送数据内容
     * @param url 地址
     */
    private static void sendByWebhook(Object data, String url) {
        try {
            cn.hutool.http.HttpResponse response = HttpUtil.createPost(url)
                    .body(JSON.toJSONString(data))
                    .execute();
            String result = response.body();
            if (response.isOk()) {
                log.debug("推送webhook消息完成，返回结果：{}", result);
            } else {
                log.error("推送失败，状态码：{}，返回消息：{}", response.getStatus(), result);
            }

        } catch (Exception ex) {
            log.error("推送Webhook消息失败", ex);
        }
    }

    /**
     * 机构删除时推送
     */
    @Async
    public void sendDeptDelete(String tenantId, Collection<String> ids) {
        this.processDataSub("dept", "delete", ids);

        if (!enabled) {
            log.warn("未启用RabbitMQ");
            return;
        }

        Msg<Collection<String>> msg = new Msg<>();
        msg.setData(ids);
        msg.setType("delete");
        Message message = new Message(JSON.toJSONString(msg).getBytes());
        rabbitTemplate.convertAndSend(deptQueue + ".topic", tenantId, message);
    }

    /**
     * 用户保存时推送消息
     * @param user 用户信息
     */
    @Async
    public void sendUser(UserDTO user) {
        this.processDataSub("user", "save", user);

        if (!enabled) {
            log.warn("未启用RabbitMQ");
            return;
        }

        Msg<UserDTO> msg = new Msg<>();
        msg.setData(user);
        msg.setType("save");
        Message message = new Message(JSON.toJSONString(msg).getBytes());
        String tenantId = user.getCurrentTenantId();
        rabbitTemplate.convertAndSend(userQueue + ".topic", tenantId, message);
    }

    /**
     * 用户删除时推送
     *
     * @param tenantId
     * @param ids      用户id列表
     */
    @Async
    public void sendUserDelete(String tenantId, Collection<String> ids) {
        this.processDataSub("user", "delete", ids);

        if (!enabled) {
            log.warn("未启用RabbitMQ");
            return;
        }

        Msg<Collection<String>> msg = new Msg<>();
        msg.setData(ids);
        msg.setType("delete");
        Message message = new Message(JSON.toJSONString(msg).getBytes());
        rabbitTemplate.convertAndSend(userQueue + ".topic", tenantId, message);
        this.processDataSub("user", "delete", ids);
    }

    @Data
    private static class Msg<T> {
        private String type;
        private T data;
    }
}
